﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Security;
using Storage;

namespace Groupware
{
    public class MessageManager
    {
        /// <summary>
        /// Returns the number of unread messages for the user usr
        /// </summary>
        /// <param name="usr">the user whose number of unread messages has to be retrieved</param>
        /// <returns>the number of unread messages for the user</returns>
        public static int GetUserUnreadMessageCount(TripLoaUser usr)
        {
            var result = (from msg in Storage.StorageManager.Instance.Entities.ReceivedMessages
                          where msg.ReceiverUserId == usr.UserID
                          && msg.IsRead == false
                          select msg).Count();
            return result;
        }

        /// <summary>
        /// Retrieves all the messages received by the user usr.
        /// </summary>
        /// <param name="usr">The user whose messages have to be retrieved</param>
        /// <returns>A list of messages. An empty list if there are no messages</returns>
        public static List<Message> RetrieveUserReceivedMessages(TripLoaUser usr)
        {
            //Security checks??
            List<Storage.EntityModels.ReceivedMessages> dbMessages = StorageManager.Instance.GetAllReceivedMessagesByUsername(usr.UserName);
            List<Message> messages = new List<Message>();
            foreach (Storage.EntityModels.ReceivedMessages dbMsg in dbMessages)
            {
                Message msg = new Message();
                msg.Id = dbMsg.MessageId;//dbMsg.Id; //dbMsg dovrebbe essere un Message, non un ReceivedMessage!!!!
                msg.sender = dbMsg.Sender.Username;
                msg.receiver.Add(usr.GetProfile().Username);
                msg.Title = dbMsg.Message.Title;
                msg.Text = dbMsg.Message.Text;
                msg.Priority = dbMsg.Message.Priority;
                msg.isRead = dbMsg.IsRead;
                msg.date = dbMsg.Message.Date;
                msg.sentORreceived = false;
                messages.Add(msg);
            }
            return messages;
        }

        /// <summary>
        /// Retrieves all the messages sent by the user usr
        /// </summary>
        /// <param name="usr">The user whose messages have to be retrieved</param>
        /// <returns>A list of messages. An empty list if there are no messages</returns>
        public static List<Message> RetrieveUserSentMessages(TripLoaUser usr)
        {
            //Security checks??
            List<Storage.EntityModels.SentMessages> dbMessages = StorageManager.Instance.GetAllSentMessagesByUsername(usr.UserName);
            List<Message> messages = new List<Message>();
            foreach (Storage.EntityModels.SentMessages dbMsg in dbMessages)
            {
                if (messages.Count != 0 && messages.ElementAt(messages.Count - 1).Id == dbMsg.MessageId)
                    messages.ElementAt(messages.Count - 1).receiver.Add(dbMsg.Receiver.Username);
                else
                {
                    Message msg = new Message();
                    msg.Id = dbMsg.MessageId; //dbMsg.MId;
                    msg.sender = usr.GetProfile().Username;
                    msg.receiver.Add(dbMsg.Receiver.Username);
                    msg.Title = dbMsg.Message.Title;
                    msg.Text = dbMsg.Message.Text;
                    msg.Priority = dbMsg.Message.Priority;
                    msg.date = dbMsg.Message.Date;
                    msg.sentORreceived = true;
                    msg.isRead = true;
                    messages.Add(msg);
                }
            }
            return messages;
        }

        /// <summary>
        /// Retrieves the messages received by the user usr in the given interval
        /// </summary>
        /// <param name="usr"></param>
        /// <returns>A list of messages. An empty list if there are no messages</returns>
        public static List<Message> RetrieveUserReceivedMessages(TripLoaUser usr, int from, int to)
        {
            List<Message> messages = new List<Message>();
            if (from < 0 || to < 0 || to < from) return messages;
            List<Storage.EntityModels.ReceivedMessages> dbMessages = StorageManager.Instance.GetAPageOfReceivedMessages(usr.UserName,from,to-from+1);
            foreach (Storage.EntityModels.ReceivedMessages dbMsg in dbMessages)
            {
                Message msg = new Message();
                msg.Id = dbMsg.MessageId;
                msg.sender = dbMsg.Sender.Username;
                msg.receiver.Add(usr.GetProfile().Username);
                msg.Title = dbMsg.Message.Title;
                msg.Text = dbMsg.Message.Text;
                msg.Priority = dbMsg.Message.Priority;
                msg.isRead = dbMsg.IsRead;
                msg.date = dbMsg.Message.Date;
                msg.sentORreceived = false;
                messages.Add(msg);
            }
            return messages;
        }


        /// <summary>
        /// Retrive a single received message by message Id
        /// </summary>
        /// <param name="usr">The user whose message have to be retrieved</param>
        /// <param name="messageId">The message Id</param>
        /// <returns>A single received message</returns>
        public static Message GetReceivedMessageById(TripLoaUser usr, int messageId)
        {
            var dbMessage = StorageManager.Instance.GetReceivedMessageByUsernameAndMsgId(usr.UserName, messageId);
            Message message = new Message()
            {
                Id = dbMessage.MessageId,
                sender = dbMessage.Sender.Username,
                Title = dbMessage.Message.Title,
                Text = dbMessage.Message.Text,
                Priority = dbMessage.Message.Priority,
                isRead = dbMessage.IsRead,
                date = dbMessage.Message.Date,
                sentORreceived = false
            };
            message.receiver.Add(dbMessage.Receiver.Username);
            return message;
        }

        /// <summary>
        /// Retrieves the messages sent by the user usr in the given interval
        /// </summary>
        /// <param name="usr"></param>
        /// <returns>A list of messages. An empty list if there are no messages</returns>
        public static List<Message> RetrieveUserSentMessages(TripLoaUser usr, int from, int to)
        {
            List<Message> messages = new List<Message>();
            if (from < 0 || to < 0 || to < from) return messages;
            List<Storage.EntityModels.SentMessages> dbMessages = StorageManager.Instance.GetAPageOfSentMessages(usr.UserName, from, to - from + 1);
            foreach (Storage.EntityModels.SentMessages dbMsg in dbMessages)
            {
                if (messages.Count != 0 && messages.ElementAt(messages.Count - 1).Id == dbMsg.MessageId)
                    messages.ElementAt(messages.Count - 1).receiver.Add(dbMsg.Receiver.Username);
                else
                {
                    Message msg = new Message();
                    msg.Id = dbMsg.MessageId;
                    msg.sender = usr.GetProfile().Username;
                    msg.receiver.Add(dbMsg.Receiver.Username);
                    msg.Title = dbMsg.Message.Title;
                    msg.Text = dbMsg.Message.Text;
                    msg.Priority = dbMsg.Message.Priority;
                    msg.date = dbMsg.Message.Date;
                    msg.sentORreceived = true;
                    messages.Add(msg);
                }
            }
            return messages;
        }

        /// <summary>
        /// Marks as read the message whose id is messageId received by the user usr
        /// </summary>
        /// <param name="messageId"></param>
        public static void MarkAsRead(int messageId, TripLoaUser usr)
        {
            Storage.EntityModels.TripLoaDataContext db = StorageManager.Instance.Entities;
            StorageManager manager = StorageManager.Instance;
            try
            {
                Storage.EntityModels.ReceivedMessages dbMsg = manager.GetReceivedMessageByUsernameAndMsgId(usr.UserName, messageId);
                dbMsg.IsRead = true;
                db.SubmitChanges();
            }
            catch (Storage.Exceptions.MessageNotFoundException)
            { }
        }

        /// <summary>
        /// Marks as read the messages whose ids are contained into the list messagesId received by the user usr
        /// </summary>
        /// <param name="messagesId"></param>
        public static void MarkAsRead(List<int> messagesIds, TripLoaUser usr)
        {
            foreach (int msgId in messagesIds)
            {
                MessageManager.MarkAsRead(msgId,usr);
            }
        }

        /// <summary>
        /// Deletes the received message whose id is messageId received by the user usr
        /// </summary>
        /// <param name="messageId"></param>
        /// <param name="usr"></param>
        public static void DeleteReceivedMessageById(int messageId, TripLoaUser usr)
        {
            Storage.StorageManager.Instance.DeleteReceivedMessage(usr.UserName, messageId);
        }

        /// <summary>
        /// Deletes the sent message whose id is messageId received by the user usr
        /// </summary>
        /// <param name="messageId"></param>
        /// <param name="usr"></param>
        public static void DeleteSentMessageById(int messageId, TripLoaUser usr)
        {
            Storage.StorageManager.Instance.DeleteSentMessage(usr.UserName, messageId);
        }

        /// <summary>
        /// Deletes the messages whose ids are contained into the list messagesId received by the user usr
        /// </summary>
        /// <param name="messagesId"></param>
        /// <param name="usr"></param>
        public static void DeleteReceivedMessagesById(List<int> messageIds, TripLoaUser usr)
        {
            foreach (int msgId in messageIds)
            {
                Storage.StorageManager.Instance.DeleteReceivedMessage(usr.UserName, msgId);
            }
        }

        /// <summary>
        /// Deletes the messages whose ids are contained into the list messagesId sent by the user usr
        /// </summary>
        /// <param name="messagesId"></param>
        /// <param name="usr"></param>
        public static void DeleteSentMessagesById(List<int> messageIds, TripLoaUser usr)
        {
            foreach (int msgId in messageIds)
            {
                Storage.StorageManager.Instance.DeleteSentMessage(usr.UserName, msgId);
            }
        }

        /// <summary>
        /// Deletes all messages received by the user usr
        /// </summary>
        /// <param name="usr"></param>
        public static void DeleteAllReceivedMessagesByUser(TripLoaUser usr)
        {
            StorageManager.Instance.DeleteAllReceivedMessages(usr.UserName);
        }

        /// <summary>
        /// Deletes all messages sent by the user usr
        /// </summary>
        /// <param name="usr"></param>
        public static void DeleteAllSentMessagesByUser(TripLoaUser usr)
        {
            StorageManager.Instance.DeleteAllSentMessages(usr.UserName);
        }
    }
}
